package com.jingdianjichi.subject.domain.config;

import org.apache.commons.lang3.StringUtils;

import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 自定义名称的线程工厂
 * 用于创建具有特定名称前缀的线程，便于识别和管理。
 *
 * 这个类的主要目的是提供一种创建线程时自动赋予有意义名称的方式，从而在多线程环境中简化线程管理和问题诊断。
 * 通过自定义线程名称，开发者可以更容易地区分和识别不同线程的作用，尤其是在查看日志文件或使用调试工具时
 *
 * @author: ChickenWing
 * @date: 2023/11/26
 */
public class CustomNameThreadFactory implements ThreadFactory {

    private static final AtomicInteger poolNumber = new AtomicInteger(1); // 线程池编号，用于区分不同的线程池
    private final ThreadGroup group; // 线程组，用于管理创建的线程
    private final AtomicInteger threadNumber = new AtomicInteger(1); // 线程编号，用于给线程命名时区分不同线程
    private final String namePrefix; // 线程名称前缀，用于标识线程属于哪个线程池和它的序号

    /**
     * 构造函数，创建一个具有指定名称前缀的线程工厂。
     * 如果传入的名称为空，则默认使用"pool"作为名称前缀。
     *
     * @param name 线程名称前缀
     */
    CustomNameThreadFactory(String name) {
        SecurityManager s = System.getSecurityManager();
        group = (s != null) ? s.getThreadGroup() :
                Thread.currentThread().getThreadGroup(); // 获取安全管理器指定的线程组，如果没有则使用当前线程的线程组
        if (StringUtils.isBlank(name)) {
            name = "pool"; // 如果未指定名称，则使用默认名称"pool"
        }
        namePrefix = name + "-" +
                poolNumber.getAndIncrement() +
                "-thread-"; // 构造线程名称前缀，包含自定义名称、线程池编号和"thread-"
    }

    /**
     * 创建新线程的方法。
     * 使用指定的Runnable对象和构造时定义的名称前缀创建新线程。
     *
     * @param r 要在新线程中执行的Runnable任务
     * @return 创建的新线程
     */
    @Override
    public Thread newThread(Runnable r) {
        Thread t = new Thread(group, r,
                namePrefix + threadNumber.getAndIncrement(),
                0); // 创建新线程，名称包含前缀和线程编号
        if (t.isDaemon()){
            t.setDaemon(false); // 确保线程不是守护线程
        }
        if (t.getPriority() != Thread.NORM_PRIORITY){
            t.setPriority(Thread.NORM_PRIORITY); // 确保线程具有正常优先级
        }
        return t;
    }

}
